from sqlalchemy import or_, and_
from datetime import datetime
from app import lxq
from app.dao.project.ProjectRoleDao import ProjectRoleDao
from app.dao.testcase.TestCaseDao import TestCaseDao
from app.models import db
from app.models.project import Project
from app.utils.logger import Log


class ProjectDao(object):
    log = Log("ProjectDao")

    @staticmethod
    def list_project(user, role, page, size, name=None):
        """
        查询/获取项目列表
        :param user: 当前用户
        :param role:  当前用户角色
        :param page:  当前页码
        :param size:  当前size
        :param name:  项目名称
        :return:

先判断用户是不是ADMIN，如果不是，则查询一下这个用户拥有的项目，等于说是转换了我们刚才写的sql。

最后通过项目的创建时间进行了排序，并进行了分页并返回了项目总数，第三个参数是error信息。
        """

        try:
            # 类名.属性名 == xxx 是filter的写法
            # 把所有筛选条件放在一个列表search里，然后用解包传递给filter
            # 筛选条件比较多的时候适合用
            search = [Project.deleted_at == None,]

            if role != lxq.config.get("ADMIN"):
                project_list,err = ProjectRoleDao.list_project_by_user(user)
                search.append(or_(Project.id in project_list, Project.owner == user, Project.private == False))
            if name:
                search.append(Project.name.ilike("%{}%".format(name)))
            # 查询条件收集完了
            data = Project.query.filter(*search)
            # select * from project where deleted_at is null and (owner = user or project_id in (已经查出的用户项目) or private is false);
            # 统计记录条数 count
            total = data.count()
            # print(total)
            #  paginate().items 获当前页的对象 列表
            # 返回当前页的对象列表、总数、错误
            return data.order_by(Project.created_at.desc()).paginate(page, per_page=size).items, total, None
        except Exception as e:
            ProjectDao.log.error(f"获取用户: {user}项目列表失败, {e}")
            return [], 0, f"获取用户: {user}项目列表失败, {e}"


    @staticmethod
    def add_project(name,owner,create_user, description, private):
        '''

        :param name:
        :param owner:
        :param user:
        :param private:
        :return:
        '''
        try:
            # 先判断项目名是否存在 并且 已被删除
            data = Project.query.filter_by(name=name,deleted_at=None).first()
            if data is not None:
                return "项目已存在"
            pr = Project(name, owner, create_user, description, private)
            db.session.add(pr)
            db.session.commit()
        except Exception as e:
            ProjectDao.log.error(f"新增项目 {name} 失败， {e}")
            return  f"新增项目 {name} 失败， {e}"
        return None

    @staticmethod
    def query_project(project_id: int):
        '''
        返回项目详情、项目中的成员角色列表、用例数、error
        :param project_id:
        :return:
        '''
        try:
            #  注意id 不是写错了
            # 通过project_id去获取这个项目的所有角色列表。
            data = Project.query.filter_by(id=project_id, deleted_at=None).first()
            # print(data)
            # print(data.owner)
            if data is None:
                return None, [], "项目不存在"
            roles, err = ProjectRoleDao.list_role(project_id)

            tree = TestCaseDao.list_test_case(project_id)
            if err:
                return None, [], [], err

            return data, roles, tree, None

        except Exception as e:
            ProjectDao.log.error(f"查询项目：{project_id} 失败， {e}")
            return None, [], f"查询项目：{project_id} 失败， {e}"



    @staticmethod
    def update_project(creat_user, role, project_id, name, owner,private,description):
        '''
        项目详情编辑
        只有项目负责人和超级管理员可以编辑项目，
        所以一旦owner发生变更，则需要对权限做一个判断。
        最后就是记得更改更新时间和更新人。
        :param user:
        :param role:
        :param project_id:
        :param name:
        :param owner:
        :param private:
        :param description:
        :return:
        '''
        try:
            data = Project.query.filter_by(id=project_id, deleted_at=None).first()
            if data is None:
                return "项目不存在"

            # 如果修改人不是owner 或者 超管
            if data.owner != owner and (role < lxq.config.get("ADMIN") or creat_user != data.owner):
                return "您没有权限修改项目负责人"

            data.name = name
            data.owner = owner
            data.private=private
            data.description=description
            data.update_at = datetime.now()
            data.update_user = user
            db.session.commit()

        except Exception as e:
            ProjectDao.log.error(f"编辑项目：{name} 失败， {e}")
            return f"编辑项目：{name} 失败， {e}"

        return None
